using AuthService.Domain.Entities;
using AuthService.Domain.Enums;
using AuthService.Domain.Repositories;
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
using HttpMethod = AuthService.Domain.Enums.HttpMethod;

namespace AuthService.Application.Services;

/// <summary>
/// 动态API服务接口
/// 提供运行时API配置和路由匹配功能
/// </summary>
public interface IDynamicApiService
{
    /// <summary>
    /// 根据请求路径和方法查找匹配的API端点
    /// </summary>
    /// <param name="requestPath">请求路径</param>
    /// <param name="method">HTTP方法</param>
    /// <param name="tenantId">租户ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>匹配的API端点</returns>
    Task<DynamicApiEndpoint?> FindMatchingEndpointAsync(string requestPath, HttpMethod method, string? tenantId = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有启用的API端点
    /// </summary>
    /// <param name="tenantId">租户ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>API端点列表</returns>
    Task<IEnumerable<DynamicApiEndpoint>> GetEnabledEndpointsAsync(string? tenantId = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据ID获取API端点
    /// </summary>
    /// <param name="id">端点ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>API端点</returns>
    Task<DynamicApiEndpoint?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);

    /// <summary>
    /// 创建新的API端点
    /// </summary>
    /// <param name="endpoint">API端点</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>创建的API端点</returns>
    Task<DynamicApiEndpoint> CreateEndpointAsync(DynamicApiEndpoint endpoint, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新API端点
    /// </summary>
    /// <param name="endpoint">API端点</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>更新的API端点</returns>
    Task<DynamicApiEndpoint> UpdateEndpointAsync(DynamicApiEndpoint endpoint, CancellationToken cancellationToken = default);

    /// <summary>
    /// 删除API端点
    /// </summary>
    /// <param name="id">端点ID</param>
    /// <param name="deletedBy">删除者</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否成功</returns>
    Task<bool> DeleteEndpointAsync(Guid id, string? deletedBy = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 启用API端点
    /// </summary>
    /// <param name="id">端点ID</param>
    /// <param name="updatedBy">更新者</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否成功</returns>
    Task<bool> EnableEndpointAsync(Guid id, string? updatedBy = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 禁用API端点
    /// </summary>
    /// <param name="id">端点ID</param>
    /// <param name="updatedBy">更新者</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否成功</returns>
    Task<bool> DisableEndpointAsync(Guid id, string? updatedBy = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 记录API端点访问
    /// </summary>
    /// <param name="id">端点ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否成功</returns>
    Task<bool> RecordAccessAsync(Guid id, CancellationToken cancellationToken = default);

    /// <summary>
    /// 验证API端点配置
    /// </summary>
    /// <param name="endpoint">API端点</param>
    /// <returns>验证结果</returns>
    ValidationResult ValidateEndpoint(DynamicApiEndpoint endpoint);

    /// <summary>
    /// 检查路径是否匹配模板
    /// </summary>
    /// <param name="requestPath">请求路径</param>
    /// <param name="pathTemplate">路径模板</param>
    /// <returns>是否匹配及参数</returns>
    (bool IsMatch, Dictionary<string, string> Parameters) MatchPath(string requestPath, string pathTemplate);
}

/// <summary>
/// 动态API服务实现
/// </summary>
public partial class DynamicApiService : IDynamicApiService
{
    private readonly IDynamicApiEndpointRepository _endpointRepository;
    private readonly ILogger<DynamicApiService> _logger;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="endpointRepository">端点仓储</param>
    /// <param name="logger">日志记录器</param>
    public DynamicApiService(IDynamicApiEndpointRepository endpointRepository, ILogger<DynamicApiService> logger)
    {
        _endpointRepository = endpointRepository;
        _logger = logger;
    }

    /// <summary>
    /// 根据请求路径和方法查找匹配的API端点
    /// </summary>
    public async Task<DynamicApiEndpoint?> FindMatchingEndpointAsync(string requestPath, HttpMethod method, string? tenantId = null, CancellationToken cancellationToken = default)
    {
        try
        {
            // 获取所有可能匹配的端点
            var endpoints = await _endpointRepository.GetMatchingEndpointsAsync(requestPath, method, tenantId, cancellationToken);

            // 按优先级排序，找到最佳匹配
            foreach (var endpoint in endpoints.OrderByDescending(e => e.Priority))
            {
                var (isMatch, parameters) = MatchPath(requestPath, endpoint.PathTemplate);
                if (isMatch)
                {
                    _logger.LogDebug("找到匹配的API端点: {EndpointName}, 路径: {Path}, 方法: {Method}",
                        endpoint.Name, endpoint.PathTemplate, endpoint.Method);
                    return endpoint;
                }
            }

            _logger.LogDebug("未找到匹配的API端点，路径: {Path}, 方法: {Method}", requestPath, method);
            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "查找匹配API端点失败，路径: {Path}, 方法: {Method}", requestPath, method);
            throw;
        }
    }

    /// <summary>
    /// 获取所有启用的API端点
    /// </summary>
    public async Task<IEnumerable<DynamicApiEndpoint>> GetEnabledEndpointsAsync(string? tenantId = null, CancellationToken cancellationToken = default)
    {
        try
        {
            return await _endpointRepository.GetEnabledEndpointsAsync(tenantId, cancellationToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取启用的API端点失败");
            throw;
        }
    }

    /// <summary>
    /// 根据ID获取API端点
    /// </summary>
    public async Task<DynamicApiEndpoint?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        try
        {
            return await _endpointRepository.GetByIdAsync(id, cancellationToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据ID获取API端点失败: {EndpointId}", id);
            throw;
        }
    }

    /// <summary>
    /// 创建新的API端点
    /// </summary>
    public async Task<DynamicApiEndpoint> CreateEndpointAsync(DynamicApiEndpoint endpoint, CancellationToken cancellationToken = default)
    {
        try
        {
            // 验证端点配置
            var validationResult = ValidateEndpoint(endpoint);
            if (!validationResult.IsValid)
            {
                throw new ArgumentException($"API端点配置无效: {string.Join(", ", validationResult.Errors)}");
            }

            // 检查是否已存在相同的路径和方法组合
            var exists = await _endpointRepository.ExistsByPathAndMethodAsync(
                endpoint.PathTemplate, endpoint.Method, endpoint.TenantId, cancellationToken: cancellationToken);

            if (exists)
            {
                throw new InvalidOperationException($"相同路径和方法的API端点已存在: {endpoint.PathTemplate} {endpoint.Method}");
            }

            var createdEndpoint = await _endpointRepository.CreateAsync(endpoint, cancellationToken);

            _logger.LogInformation("API端点创建成功: {EndpointName}, 路径: {Path}, 方法: {Method}",
                endpoint.Name, endpoint.PathTemplate, endpoint.Method);

            return createdEndpoint;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建API端点失败: {EndpointName}", endpoint.Name);
            throw;
        }
    }

    /// <summary>
    /// 更新API端点
    /// </summary>
    public async Task<DynamicApiEndpoint> UpdateEndpointAsync(DynamicApiEndpoint endpoint, CancellationToken cancellationToken = default)
    {
        try
        {
            // 验证端点配置
            var validationResult = ValidateEndpoint(endpoint);
            if (!validationResult.IsValid)
            {
                throw new ArgumentException($"API端点配置无效: {string.Join(", ", validationResult.Errors)}");
            }

            // 检查是否已存在相同的路径和方法组合（排除当前端点）
            var exists = await _endpointRepository.ExistsByPathAndMethodAsync(
                endpoint.PathTemplate, endpoint.Method, endpoint.TenantId, endpoint.Id, cancellationToken);

            if (exists)
            {
                throw new InvalidOperationException($"相同路径和方法的API端点已存在: {endpoint.PathTemplate} {endpoint.Method}");
            }

            endpoint.MarkAsUpdated();
            var updatedEndpoint = await _endpointRepository.UpdateAsync(endpoint, cancellationToken);

            _logger.LogInformation("API端点更新成功: {EndpointName}, ID: {EndpointId}",
                endpoint.Name, endpoint.Id);

            return updatedEndpoint;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新API端点失败: {EndpointId}", endpoint.Id);
            throw;
        }
    }

    /// <summary>
    /// 删除API端点
    /// </summary>
    public async Task<bool> DeleteEndpointAsync(Guid id, string? deletedBy = null, CancellationToken cancellationToken = default)
    {
        try
        {
            var success = await _endpointRepository.DeleteAsync(id, deletedBy, cancellationToken);

            if (success)
            {
                _logger.LogInformation("API端点删除成功: {EndpointId}", id);
            }
            else
            {
                _logger.LogWarning("API端点删除失败，端点不存在: {EndpointId}", id);
            }

            return success;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "删除API端点失败: {EndpointId}", id);
            throw;
        }
    }

    /// <summary>
    /// 启用API端点
    /// </summary>
    public async Task<bool> EnableEndpointAsync(Guid id, string? updatedBy = null, CancellationToken cancellationToken = default)
    {
        try
        {
            var endpoint = await _endpointRepository.GetByIdAsync(id, cancellationToken);
            if (endpoint == null)
            {
                _logger.LogWarning("启用API端点失败，端点不存在: {EndpointId}", id);
                return false;
            }

            endpoint.Enable(updatedBy);
            await _endpointRepository.UpdateAsync(endpoint, cancellationToken);

            _logger.LogInformation("API端点启用成功: {EndpointId}", id);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "启用API端点失败: {EndpointId}", id);
            throw;
        }
    }

    /// <summary>
    /// 禁用API端点
    /// </summary>
    public async Task<bool> DisableEndpointAsync(Guid id, string? updatedBy = null, CancellationToken cancellationToken = default)
    {
        try
        {
            var endpoint = await _endpointRepository.GetByIdAsync(id, cancellationToken);
            if (endpoint == null)
            {
                _logger.LogWarning("禁用API端点失败，端点不存在: {EndpointId}", id);
                return false;
            }

            endpoint.Disable(updatedBy);
            await _endpointRepository.UpdateAsync(endpoint, cancellationToken);

            _logger.LogInformation("API端点禁用成功: {EndpointId}", id);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "禁用API端点失败: {EndpointId}", id);
            throw;
        }
    }

    /// <summary>
    /// 记录API端点访问
    /// </summary>
    public async Task<bool> RecordAccessAsync(Guid id, CancellationToken cancellationToken = default)
    {
        try
        {
            var success = await _endpointRepository.RecordAccessAsync(id, cancellationToken);

            if (success)
            {
                _logger.LogDebug("API端点访问记录成功: {EndpointId}", id);
            }
            else
            {
                _logger.LogWarning("API端点访问记录失败，端点不存在: {EndpointId}", id);
            }

            return success;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "记录API端点访问失败: {EndpointId}", id);
            throw;
        }
    }

    /// <summary>
    /// 验证API端点配置
    /// </summary>
    public ValidationResult ValidateEndpoint(DynamicApiEndpoint endpoint)
    {
        return endpoint.ValidateConfiguration();
    }

    /// <summary>
    /// 检查路径是否匹配模板
    /// </summary>
    public (bool IsMatch, Dictionary<string, string> Parameters) MatchPath(string requestPath, string pathTemplate)
    {
        var parameters = new Dictionary<string, string>();

        try
        {
            // 移除开头和结尾的斜杠，统一格式
            requestPath = requestPath.Trim('/');
            pathTemplate = pathTemplate.Trim('/');

            // 如果都为空，则匹配
            if (string.IsNullOrEmpty(requestPath) && string.IsNullOrEmpty(pathTemplate))
            {
                return (true, parameters);
            }

            // 将路径模板转换为正则表达式
            var regexPattern = ConvertPathTemplateToRegex(pathTemplate, out var parameterNames);
            var regex = new Regex($"^{regexPattern}$", RegexOptions.IgnoreCase);

            var match = regex.Match(requestPath);
            if (!match.Success)
            {
                return (false, parameters);
            }

            // 提取路径参数
            for (int i = 0; i < parameterNames.Count; i++)
            {
                if (match.Groups.Count > i + 1)
                {
                    parameters[parameterNames[i]] = Uri.UnescapeDataString(match.Groups[i + 1].Value);
                }
            }

            return (true, parameters);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "路径匹配失败，请求路径: {RequestPath}, 模板: {PathTemplate}", requestPath, pathTemplate);
            return (false, parameters);
        }
    }

    /// <summary>
    /// 将路径模板转换为正则表达式
    /// </summary>
    /// <param name="pathTemplate">路径模板</param>
    /// <param name="parameterNames">参数名称列表</param>
    /// <returns>正则表达式模式</returns>
    private string ConvertPathTemplateToRegex(string pathTemplate, out List<string> parameterNames)
    {
        var parameters = new List<string>();
        parameterNames = parameters;

        if (string.IsNullOrEmpty(pathTemplate))
        {
            return string.Empty;
        }

        // 转义正则表达式特殊字符
        var pattern = Regex.Escape(pathTemplate);

        // 替换路径参数 {id} -> ([^/]+)
        var parameterRegex = new Regex(@"\\{([^}]+)\\}");
        pattern = parameterRegex.Replace(pattern, match =>
        {
            var paramName = match.Groups[1].Value;
            parameters.Add(paramName);
            return "([^/]+)";
        });

        // 替换通配符 * -> ([^/]*)
        pattern = pattern.Replace(@"\*", "([^/]*)");

        // 替换双通配符 ** -> (.*)
        pattern = pattern.Replace(@"\*\*", "(.*)");

        return pattern;
    }
}
